package com.glela.activ.service.impl;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.glela.activ.dao.OActivDao;
import com.glela.activ.mapper.OActivContentExpressMapper;
import com.glela.activ.mapper.OActivContentMoneyMapper;
import com.glela.activ.mapper.OActivGiftProductMapper;
import com.glela.activ.mapper.OActivMapper;
import com.glela.activ.model.OActiv;
import com.glela.activ.model.OActivContentExpress;
import com.glela.activ.model.OActivContentMoney;
import com.glela.activ.model.OActivGiftProduct;
import com.glela.activ.model.OActivitiesInfo;
import com.glela.activ.service.OActivService;
import com.glela.activ.service.domain.OActivAvlInfoVo;
import com.glela.activ.service.domain.OActivAvlProductVo;
import com.glela.activ.service.domain.OActivAvlVo;
import com.glela.activ.service.domain.OActivProductParam;
import com.glela.activ.service.domain.avl.OActivAvlGiftProductVo;
import com.glela.activ.service.domain.info.OActivInfoConditionSaleAmountVo;
import com.glela.activ.service.domain.info.OActivInfoContentGiftVo;
import com.glela.activ.service.domain.info.OActivInfoContentMoneyVo;
import com.glela.activ.service.domain.info.OActivInfoVo;
import com.glela.activ.service.domain.info.gift.OActivInfoContentGiftProductVo;
import com.glela.cache.redis.RedisKeys;
import com.glela.cache.redis.RedisUtil;
import com.glela.common.util.DateUtil;
import com.glela.common.util.JsonUtil;

@Service
public class OActivServiceImpl implements OActivService {
	private static Logger LOGGER = LoggerFactory.getLogger(OActivServiceImpl.class);

	@Autowired
	private RedisUtil redisUtil;

	@Autowired
	private OActivDao					oActivDao;
	@Autowired
	private OActivMapper				oActivMapper;
	@Autowired
	private OActivContentExpressMapper	oActivContentExpressMapper;
	@Autowired
	private OActivContentMoneyMapper	oActivContentMoneyMapper;
	@Autowired
	private OActivGiftProductMapper		oActivGiftProductMapper;

	@Override
	public OActivAvlInfoVo queryProductActiv(final OActivProductParam activProductParam) {
		Set<OActivProductParam> hashSet = new HashSet<>();
		hashSet.add(activProductParam);
		return queryProductActiv(hashSet);
	}

	@Override
	public OActivAvlInfoVo queryProductActiv(Set<OActivProductParam> activProductParams) {
		String nowTime = DateUtil.getNow();//当前时间
		return queryProductActiv(activProductParams, nowTime);
	}

	@Override
	public OActivAvlInfoVo queryProductActiv(Set<OActivProductParam> activProductParams, String nowTime) {
		if (CollectionUtils.isEmpty(activProductParams) || nowTime == null) {
			return null;
		}
		OActivAvlInfoVo rslActivProduct = new OActivAvlInfoVo();

		//校验sku是否重复
		Map<Long, Boolean> _check_repeat_sku_map = new HashMap<>();
		for (OActivProductParam oActivProductVo : activProductParams) {
			if (oActivProductVo == null || oActivProductVo.getProductId() < 1) {
				throw new IllegalArgumentException("productId is null");
			}
			if (oActivProductVo.getSalePrice() < 0) {
				throw new IllegalArgumentException("sale price is less than 0");
			}
			if (oActivProductVo.getQuantity() < 1) {
				throw new IllegalArgumentException("quantity is less than 0");
			}
			if (MapUtils.getBooleanValue(_check_repeat_sku_map, oActivProductVo.getProductId(), false)) {
				throw new IllegalArgumentException("productId is re");
			} else {
				_check_repeat_sku_map.put(oActivProductVo.getProductId(), true);
			}
		}
		_check_repeat_sku_map = null;

		Map<Long, Long> activTotalPriceMap = new HashMap<>();
		Map<Long, OActivAvlVo> avlActivMap = new HashMap<>();
		//统计符合活动的商品参与的活动
		for (OActivProductParam activProductParam : activProductParams) {
			//根据货品id查询活动
			OActiv oActiv = queryByProductId(activProductParam.getProductId(), nowTime);
			if (oActiv == null || oActiv.getIsValid() != 1 || oActiv.getDelFlag() != 0) {
				//分组未参与活动商品
				rslActivProduct.getUavlActivProducts().add(activProductParam);
			} else {
				long activId = oActiv.getId();
				OActivAvlProductVo addActivAvlProductVo = new OActivAvlProductVo();
				addActivAvlProductVo.setActivId(activId);
				addActivAvlProductVo.setProductId(activProductParam.getProductId());
				addActivAvlProductVo.setSalePrice(activProductParam.getSalePrice());
				addActivAvlProductVo.setQuantity(activProductParam.getQuantity());
				addActivAvlProductVo.setPromotionFee(activProductParam.getPromotionFee());

				activTotalPriceMap.put(activId, MapUtils.getLongValue(activTotalPriceMap, activId, 0) + activProductParam.getSalePrice() * activProductParam.getQuantity() - activProductParam.getPromotionFee());
				OActivAvlVo avlActiv = avlActivMap.get(activId);
				if (avlActiv == null) {
					avlActiv = new OActivAvlVo();
					avlActivMap.put(activId, avlActiv);

					avlActiv.setActivId(activId);
					avlActiv.setActivType(oActiv.getActivType());
				}
				avlActiv.getAvlActivProducts().add(addActivAvlProductVo);
			}
		}
		//计算参与活动商品优惠信息
		for (long activId : avlActivMap.keySet()) {
			OActivAvlVo avlActiv = avlActivMap.get(activId);
			//查询活动详细信息
			OActivInfoVo checkActivInfo = queryOActivInfo(activId);
			if (checkActivInfo == null) {
				LOGGER.warn("订单活动{}在使用过程中被删除", activId);
				//				rslActivProduct.getUavlActivProducts().addAll(avlActivMap.get(activId).getAvlActivProducts());
				throw new NullPointerException("活动被删除");
			} else {
				long _activ_product_total_price = MapUtils.getLongValue(activTotalPriceMap, activId, 0);//活动商品总销售金额
				List<OActivInfoConditionSaleAmountVo> conditionSalesAmounts = checkActivInfo.getConditions().getConditionSalesAmount();
				switch (checkActivInfo.getActivType()) {
					//判断销售金额
					case 1://普通优惠
						if (CollectionUtils.isEmpty(conditionSalesAmounts) || conditionSalesAmounts.size() > 1) {
							LOGGER.error("活动{}普通优惠限制条件异常", activId);
							throw new IllegalArgumentException("活动设置异常");
						}
						OActivInfoConditionSaleAmountVo checkActivConditionSaleAmount1 = checkActivInfo.getConditions().getConditionSalesAmount().get(0);
						if (_calcActivDiscontFee(avlActiv, _activ_product_total_price, checkActivConditionSaleAmount1)) {
							rslActivProduct.getAvlActivs().add(avlActiv);
						}
						break;

					case 2://多级优惠
						for (OActivInfoConditionSaleAmountVo checkActivConditionSaleAmount2 : conditionSalesAmounts) {
							if (_calcActivDiscontFee(avlActiv, _activ_product_total_price, checkActivConditionSaleAmount2)) {
								rslActivProduct.getAvlActivs().add(avlActiv);
								break;
							}
						}
						break;
					//判断件数
					//					case 3:
					//					case 4:

					default:
						LOGGER.warn("订单活动{}暂不支持", activId);
						throw new IllegalArgumentException("活动类型暂不支持");
				}
			}

		}
		//		if (LOGGER.isDebugEnabled()) {
		//			LOGGER.error("在{}时，商品[{}]参与活动信息：{}", nowTime, JSON.toJSONString(activProductParams), JSON.toJSONString(rslActivProduct));
		//		}
		//返回结果
		return rslActivProduct;
	}

	private boolean _calcActivDiscontFee(OActivAvlVo avlActiv, long procutTotalPrice, OActivInfoConditionSaleAmountVo checkActivConditionSaleAmount) {
		if (procutTotalPrice >= checkActivConditionSaleAmount.getStartAmount() && procutTotalPrice < checkActivConditionSaleAmount.getEndAmount()) {
			long activId = avlActiv.getActivId();
			//			avlActiv.getConditions().getConditionSalesAmount().add(checkActivConditionSaleAmount1);
			//符合条件，赠送
			OActivInfoContentMoneyVo activContentMoney = checkActivConditionSaleAmount.getMoney();
			if (activContentMoney != null) {
				long _discont_fee = 0;//活动抵扣金额
				switch (activContentMoney.getDiscountType()) {
					case 0://立减
						_discont_fee = procutTotalPrice - activContentMoney.getDiscountFee();
						if (_discont_fee < 0) {
							_discont_fee = activContentMoney.getDiscountFee() + _discont_fee;
						} else {
							_discont_fee = activContentMoney.getDiscountFee();
						}
						break;
					case 1://折扣
						_discont_fee = procutTotalPrice * (100 - activContentMoney.getDiscountFee());
						if (_discont_fee < 0) {
							_discont_fee = procutTotalPrice;
						}
						if (activContentMoney.getIsRound() == 1) {//取整
							_discont_fee = _discont_fee / 100 * 100;
						}
						break;

					default:
						LOGGER.error("活动{}-条件{}-内容立减{}-类型未知{}", activId, activContentMoney.getActivConditionId(), activContentMoney.getId(), activContentMoney.getDiscountType());
						throw new IllegalArgumentException("活动立减金额类型未知");
				}
				if (avlActiv.getActivType() == 1) {
					//折扣翻倍
					if (activContentMoney.getIsDouble() == 1 && checkActivConditionSaleAmount.getStartAmount() > 0) {
						_discont_fee = _discont_fee * (procutTotalPrice / checkActivConditionSaleAmount.getStartAmount());
						if (procutTotalPrice < _discont_fee) {//翻倍金额，最大不能大于商品总售价
							_discont_fee = procutTotalPrice;
						}
					}
				}

				//最大抵扣额不能超过限值
				Long discountFeeMax = checkActivConditionSaleAmount.getMoney().getDiscountFeeMax();
				if (discountFeeMax != null && discountFeeMax > 0 && discountFeeMax.longValue() < _discont_fee) {
					_discont_fee = discountFeeMax;
				}
				//设置活动抵扣总金额
				avlActiv.setDiscontFee(_discont_fee);

				long _surplus_discont_fee = avlActiv.getDiscontFee();//剩余活动抵扣金额
				//分摊每个活动商品优惠金额
				int i = avlActiv.getAvlActivProducts().size();
				for (OActivAvlProductVo activProductVo : avlActiv.getAvlActivProducts()) {
					if (--i == 0) {
						activProductVo.setDiscontFee(_surplus_discont_fee);
					} else {
						activProductVo.setDiscontFee(Math.round(avlActiv.getDiscontFee() * ((1d * activProductVo.getSalePrice() * activProductVo.getQuantity()) / procutTotalPrice)));
						if (_surplus_discont_fee < activProductVo.getDiscontFee()) {
							activProductVo.setDiscontFee(_surplus_discont_fee);
						}
						_surplus_discont_fee -= activProductVo.getDiscontFee();
					}
				}
			}
			//邮费+
			if (checkActivConditionSaleAmount.getExpress() != null) {
				avlActiv.setPostFee(checkActivConditionSaleAmount.getExpress().getPostFee());
				if (avlActiv.getPostFee() < 0) {
					avlActiv.setPostFee(0);
				}
				if (avlActiv.getPostFee() == 0) {
					avlActiv.setFreeShipping(true);
				}
			}
			//赠品
			OActivInfoContentGiftVo checkGifts = checkActivConditionSaleAmount.getGifts();
			if (checkGifts != null) {
				if (CollectionUtils.isNotEmpty(checkGifts.getGiftProducts())) {
					for (OActivInfoContentGiftProductVo giftProduct : checkGifts.getGiftProducts()) {
						OActivAvlGiftProductVo addOActivAvlGiftProductVo = new OActivAvlGiftProductVo();
						avlActiv.getGifts().getProducts().add(addOActivAvlGiftProductVo);

						addOActivAvlGiftProductVo.setActivId(giftProduct.getActivId());

						addOActivAvlGiftProductVo.setProductPrice(giftProduct.getProductPrice());
						addOActivAvlGiftProductVo.setSalePrice(giftProduct.getSalePrice());
						addOActivAvlGiftProductVo.setSettlementPrice(giftProduct.getSettlementPrice());
						addOActivAvlGiftProductVo.setGoodsType(giftProduct.getGoodsType());

						addOActivAvlGiftProductVo.setQuantity(giftProduct.getGiftNum());
						addOActivAvlGiftProductVo.setBrandName(giftProduct.getBrandName());
						addOActivAvlGiftProductVo.setGoodsName(giftProduct.getGoodsName());
						addOActivAvlGiftProductVo.setSpecName(giftProduct.getSpecName());
						addOActivAvlGiftProductVo.setThumbnail(giftProduct.getThumbnail());

						addOActivAvlGiftProductVo.setStoreId(giftProduct.getStoreId());
						addOActivAvlGiftProductVo.setInventoryId(giftProduct.getInventoryId());
						addOActivAvlGiftProductVo.setInventoryNum(giftProduct.getInventoryNum());
						addOActivAvlGiftProductVo.setBrandId(giftProduct.getBrandId());
						addOActivAvlGiftProductVo.setProductId(giftProduct.getProductId());
						addOActivAvlGiftProductVo.setGoodsId(giftProduct.getGoodsId());

					}
				}
			}
			return true;
		}
		return false;
	}

	@Override
	public OActiv queryByProductId(long productId, String activTime) {
		if (productId < 1 || StringUtils.isBlank(activTime)) {
			LOGGER.warn("规格productId{}在时间{}点无活动", productId, activTime);
			return null;
		}
		return oActivDao.queryByProductId(productId, activTime);
	}

	@Override
	public OActivInfoVo queryOActivInfo(long activId) {
		OActivInfoVo oActivInfoVo = null;
		//1.从缓存获取
		String key = RedisKeys.ORDER_ACTIV_ID + activId;
		String string = null;
		boolean isCache = true;
		try {
			string = redisUtil.get(key);
		} catch (Exception e) {
			isCache = false;
			LOGGER.warn("缓存连接异常：{}", e.getMessage());
		}
		if (StringUtils.isEmpty(string)) {
			//2.缓存获取不到，从数据库读取
			oActivInfoVo = oActivDao.queryInfoById(activId);
			//3.将从数据库查询的数据缓存
			if (oActivInfoVo != null && isCache) {
				redisUtil.setex(key, 1800, JSON.toJSONString(oActivInfoVo));
			}
		} else {
			//转换实体
			try {
				oActivInfoVo = JsonUtil.toBean(string, OActivInfoVo.class);
			} catch (Exception e) {
				LOGGER.warn("缓存获取订单活动详情{}转换实体类异常{}：{}", activId, string, e.getMessage());
				oActivInfoVo = oActivDao.queryInfoById(activId);
				if (isCache) {//移除异常数据
					redisUtil.del(key);
				}
			}
		}
		key = null;
		//5.返回结果
		return oActivInfoVo;
	}

	@Override
	public OActivitiesInfo getOActivitiesInfo(Long goodsId, Long activId) {
		OActivitiesInfo oActivitiesInfo = new OActivitiesInfo();
		OActiv oActiv = new OActiv();
		if (activId == 0) {
			oActiv = this.oActivMapper.selectOActivByGoodsId(goodsId);// 活动信息
		} else {
			oActiv = this.oActivMapper.selectByPrimaryKey(activId);
		}
		if (oActiv == null) {
			return null;
		}
		List<OActivContentExpress> oActivContentExpressList = this.oActivContentExpressMapper.selectOActivContentExpressByActivId(oActiv.getId());// 运费集合
		List<OActivContentMoney> oActivContentMoneyList = this.oActivContentMoneyMapper.selectOActivContentMoneyByActivId(oActiv.getId());// 满减、打折集合
		List<OActivGiftProduct> oActivGiftProductList = this.oActivGiftProductMapper.selectOActivGiftProductByActivId(oActiv.getId());// 满赠集合
		oActivitiesInfo.setoActiv(oActiv);
		oActivitiesInfo.setoActivContentExpressList(oActivContentExpressList);
		oActivitiesInfo.setoActivContentMoneyList(oActivContentMoneyList);
		oActivitiesInfo.setoActivGiftProductList(oActivGiftProductList);
		return oActivitiesInfo;
	}
}